﻿using CPPEI.Coolzon.Common;
using CPPEI.Coolzon.Metadata;
using CPPEI.Coolzon.Service;
using CPPEI.Coolzon.Service.UpdateService;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace CPPEI.Coolzon.Server
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class UpdateService : IUpdateService
    {
        /// <summary>
        /// 获取计划更新的文件
        /// </summary>
        /// <param name="appType"></param>
        /// <param name="appVersion"></param>
        /// <returns></returns>
        public Service.UpdateService.UpdateSchedule GetUpdateSchedule(string appType, string appVersion)
        {
            Service.UpdateService.UpdateSchedule result = null;
            try
            {
                Logger.Info(this.GetType().Name, string.Format("{0} localVersion:{1}开始更新", appType, appVersion));

                string targetVersion = ""; 
                XmlDocument xmlUpdateFile = new XmlDocument(); 
                string scheduleFilePath = CZEnvironment.GetBaseDirectory() + string.Format("Patchs\\{0}\\version.xml", appType);
                if (System.IO.File.Exists(scheduleFilePath))
                {
                   
                    XmlReaderSettings settings = new XmlReaderSettings();
                    settings.IgnoreComments = true;
                    XmlReader reader = XmlReader.Create(scheduleFilePath, settings);
                    xmlUpdateFile.Load(reader);
                    targetVersion = xmlUpdateFile.SelectSingleNode("Version/LatestVersion").InnerText;
                }

                Version vApp = new Version("0.0.0.0");
                if (!string.IsNullOrEmpty(appVersion))
                {
                    vApp = Version.Parse(appVersion);
                }
                Version vTarget = new Version("0.0.0.0");
                if (!string.IsNullOrEmpty(targetVersion))
                {
                    vTarget = Version.Parse(targetVersion);
                }

                if (vTarget > vApp)
                {
                    result = new Service.UpdateService.UpdateSchedule();
                    string updateFilesIncrementalPath = CZEnvironment.GetBaseDirectory() + string.Format("Patchs\\{0}\\Patch_{1}-{2}\\Patch_{3}-{4}.xml", appType, appVersion, targetVersion, appVersion, targetVersion);
                    string updateFileFullPath = CZEnvironment.GetBaseDirectory() + string.Format("Patchs\\{0}\\Patch_Full-{1}\\Patch_Full-{2}.xml", appType, targetVersion, targetVersion);
                    if (System.IO.File.Exists(updateFilesIncrementalPath))
                    {
                        //增量式补丁
                        result.Files = GetUpdateFiles(updateFilesIncrementalPath);
                        result.FromVersion = appVersion;
                        result.TargetVersion = targetVersion;
                        result.Mode = "Incremental";
                    }
                    else if (System.IO.File.Exists(updateFileFullPath))
                    {
                        //完整补丁
                        result.Files = GetUpdateFiles(updateFileFullPath);
                        result.FromVersion = appVersion;
                        result.TargetVersion = targetVersion;
                        result.Mode = "Full";
  
                    }
                    else
                    {
                        return null;
                    }
                }

                Logger.Info(this.GetType().Name, "更新完成");
                return result;
            }
            catch (Exception ex)
            {
                Logger.Error(string.Format("{0}\n{1}", ex.Message, ex.StackTrace));
            }
            return result;
        }

        /// <summary>
        /// 更新单个文件
        /// </summary>
        /// <param name="appType"></param>
        /// <param name="scheduleMode"></param>
        /// <param name="scheduleVersion"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public Service.UpdateService.UpdateResult UpdateFile(string appType, string scheduleMode, string scheduleVersion, string fileName)
        {
            Logger.Info(this.GetType().Name, string.Format("计划版本{0},开始更新程序文件{1}", scheduleVersion, fileName));
            Service.UpdateService.UpdateResult updateResult = new Service.UpdateService.UpdateResult();

            string filePath = CZEnvironment.GetBaseDirectory() + string.Format("Patchs\\{0}\\Patch_{1}-{2}\\{3}", appType, scheduleMode, scheduleVersion, fileName);

            if (System.IO.File.Exists(filePath))
            {

                if (string.IsNullOrEmpty(filePath))
                {
                    return null;
                }
                FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                try
                {
                    updateResult.Data = new byte[fs.Length];
                    fs.Seek(0, SeekOrigin.Begin);
                    fs.Read(updateResult.Data, 0, (int)fs.Length);
                    updateResult.IsSuccess = true;
                    updateResult.Message = string.Format("文件{0}更新成功！", fileName);
                    updateResult.Size = fs.Length;
                   
                    Logger.Info(this.GetType().Name, string.Format("程序文件{0}更新成功", fileName));
                    return updateResult;
                }
                catch (Exception ex)
                {
                    updateResult.IsSuccess = false;
                    updateResult.Message = ex.Message;
                    Logger.Error(this.GetType().Name, string.Format("程序文件{0}更新失败", fileName));
                }
                finally
                {
                    fs.Close();
                }

            }
            return updateResult;
        }

        /// <summary>
        /// 根据补丁地址获取文件信息
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        private List<Service.UpdateService.UpdateFile> GetUpdateFiles(string dir)
        {
            List<Service.UpdateService.UpdateFile> updateFiles = new List<Service.UpdateService.UpdateFile>();
            
            XmlDocument xmlUpdateFile = new XmlDocument();
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;
            XmlReader reader = XmlReader.Create(dir, settings);
            xmlUpdateFile.Load(reader);

            XmlNode updateFileNodes = xmlUpdateFile.SelectSingleNode("Patch");
            if (updateFileNodes == null)
            {
                return null;
            }

            for (int i = 0; i < updateFileNodes.ChildNodes.Count; i++)
            {
                UpdateFile updateFile = new Service.UpdateService.UpdateFile();
                XmlNode c = updateFileNodes.ChildNodes[i];
                updateFile.Name = c.Attributes["Name"].Value;
                updateFile.FileName = c.Attributes["Path"].Value;
                updateFile.TargetFileName = c.Attributes["TargetPath"].Value;
                updateFiles.Add(updateFile);

            }

            return updateFiles;
        }
    }
}
